package cn.com.anypay.manager.service.impl;

import cn.com.anypay.manager.common.utils.AnyJsonUtils;
import cn.com.anypay.manager.miaoma.config.Config;
import cn.com.anypay.manager.miaoma.config.ConfigService;
import cn.com.anypay.manager.service.MapService;
import cn.com.anysdk.map.config.AmapConfig;
import cn.com.anysdk.map.config.BaiduMapConfig;
import cn.com.anysdk.map.config.MapConfig;
import cn.com.anysdk.map.config.MockConfig;
import cn.com.anysdk.map.exception.MapException;
import cn.com.anysdk.map.factory.MapServiceFactory;
import cn.com.anysdk.map.model.*;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Map;

@Slf4j
@Service
public class MapServiceImpl implements MapService {

    private static final String SERVICE_TYPE = "MAP";
    @Resource
    private ConfigService configService;

    private MapConfig currentConfig;
    private cn.com.anysdk.map.service.MapService currentMapService;

    @PostConstruct
    public void init() {
        try {
            // 使用默认配置初始化，不从数据库读取
            log.info("地图服务使用默认配置初始化");
            createDefaultMapService();
            log.info("地图服务初始化成功，类型: {}", currentConfig.getType());
        } catch (Exception e) {
            log.error("地图服务初始化失败: {}", e.getMessage(), e);
            // 初始化失败时使用默认配置
            createDefaultMapService();
            log.info("由于初始化失败，使用默认Mock配置");
        }
    }

    /**
     * 创建默认的模拟地图服务
     */
    private void createDefaultMapService() {
        MockConfig mockConfig = new MockConfig();
        mockConfig.setType(MapProviderType.MOCK);
        mockConfig.setDefaultCoordinateType("wgs84");
        mockConfig.setCacheEnabled(true);
        mockConfig.setCacheExpireSeconds(3600);
        mockConfig.setLogEnabled(true);
        mockConfig.setLogLevel("INFO");

        currentConfig = mockConfig;
        currentMapService = MapServiceFactory.createMapService(currentConfig);
     }

    @Override
    public String switchProvider(Map<String, Object> config) throws MapException {
        log.info("开始切换地图服务商，配置参数: {}", config);
        try {
            String provider = (String) config.get("provider");
            if (provider == null) {
                throw new MapException("Provider is required");
            }

            // 保存配置到数据库
            Config serviceConfig = configService.saveConfig(SERVICE_TYPE, provider, config);
            log.debug("保存地图配置成功: {}", serviceConfig);

            // 创建新的地图配置
            MapConfig newConfig = createMapConfigFromMap(config);
            log.debug("创建地图配置成功: {}", newConfig);

            // 更新当前配置
            currentConfig = newConfig;

            // 创建新的地图服务实例
            currentMapService = MapServiceFactory.createMapService(newConfig);
            log.info("地图服务实例创建成功，类型: {}", newConfig.getType());

            return "Successfully switched to " + newConfig.getType() + " map provider";
        } catch (Exception e) {
            log.error("切换地图服务商失败: {}", e.getMessage(), e);
            throw new MapException("Failed to switch map provider: " + e.getMessage(), e);
        }
    }

    @Override
    public String getStaticMapUrl(String address, int zoom) {
        if (currentMapService == null) {
            log.error("地图服务未初始化");
            throw new MapException("Map provider not initialized. Please call switchProvider first.");
        }
        try {
            log.debug("获取静态地图URL，地址: {}, 缩放级别: {}", address, zoom);
            return currentMapService.getStaticMapUrl(address, zoom);
        } catch (Exception e) {
            log.error("获取静态地图URL失败，地址: {}, 错误: {}", address, e.getMessage(), e);
            throw new MapException("Failed to get static map URL: " + e.getMessage(), e);
        }
    }

    @Override
    public LocationResult geocode(String address) throws MapException {
        log.debug("开始地址解析，地址: {}", address);
        if (currentMapService == null) {
            log.error("地图服务未初始化");
            throw new MapException("Map provider not initialized. Please call switchProvider first.");
        }
        try {
            LocationResult result = currentMapService.geocode(address);
            log.debug("地址解析成功，结果: {}", result);
            return result;
        } catch (Exception e) {
            log.error("地址解析失败，地址: {}, 错误: {}", address, e.getMessage(), e);
            throw new MapException("Geocoding failed: " + e.getMessage(), e);
        }
    }

    @Override
    public AddressResult reverseGeocode(Location location) throws MapException {
        log.debug("开始逆地址解析，坐标: {}", location);
        if (currentMapService == null) {
            log.error("地图服务未初始化");
            throw new MapException("Map provider not initialized. Please call switchProvider first.");
        }
        try {
            AddressResult result = currentMapService.reverseGeocode(location);
            log.debug("逆地址解析成功，结果: {}", result);
            return result;
        } catch (Exception e) {
            log.error("逆地址解析失败，坐标: {}, 错误: {}", location, e.getMessage(), e);
            throw new MapException("Reverse geocoding failed: " + e.getMessage(), e);
        }
    }

    @Override
    public LocationResult convertCoordinate(Location location, CoordinateType fromType, CoordinateType toType) throws MapException {
        log.debug("开始坐标转换，原坐标: {}，源坐标系: {}，目标坐标系: {}", location, fromType, toType);
        if (currentMapService == null) {
            log.error("地图服务未初始化");
            throw new MapException("Map provider not initialized. Please call switchProvider first.");
        }
        try {
            LocationResult result = currentMapService.convertCoordinate(location, fromType, toType);
            log.debug("坐标转换成功，结果: {}", result);
            return result;
        } catch (Exception e) {
            log.error("坐标转换失败，原坐标: {}，源坐标系: {}，目标坐标系: {}，错误: {}",
                    location, fromType, toType, e.getMessage(), e);
            throw new MapException("Coordinate conversion failed: " + e.getMessage(), e);
        }
    }

    private MapConfig createMapConfigFromMap(Map<String, Object> config) {
        // 从配置中获取类型，支持type或provider字段
        String typeStr = (String) config.get("type");
        if (typeStr == null) {
            // 尝试从provider字段获取类型
            typeStr = (String) config.get("provider");
            if (typeStr == null) {
                log.error("缺少地图服务商类型参数");
                throw new IllegalArgumentException("Map provider type is required");
            }
        }

        MapProviderType type;
        try {
            // 处理特殊情况，数据库和前端可能发送的是小写的provider值
            if ("amap".equalsIgnoreCase(typeStr)) {
                type = MapProviderType.AMAP;
            } else if ("baidu".equalsIgnoreCase(typeStr)) {
                type = MapProviderType.BAIDU;
            } else if ("mock".equalsIgnoreCase(typeStr)) {
                type = MapProviderType.MOCK;
            } else {
                // 尝试将类型字符串转换为大写，以匹配枚举值
                try {
                    type = MapProviderType.valueOf(typeStr.toUpperCase());
                } catch (IllegalArgumentException e) {
                    log.error("不支持的地图服务商类型: {}", typeStr);
                    throw new IllegalArgumentException("Unsupported map provider type: " + typeStr);
                }
            }

            log.debug("创建地图配置，类型: {}", type);
        } catch (Exception e) {
            log.error("解析地图服务商类型失败: {}, 错误: {}", typeStr, e.getMessage());
            throw new IllegalArgumentException("Failed to parse map provider type: " + typeStr, e);
        }

        MapConfig mapConfig;
        switch (type) {
            case BAIDU:
                BaiduMapConfig baiduConfig = new BaiduMapConfig();
                baiduConfig.setType(MapProviderType.BAIDU);
                String apiKey = (String) config.get("apiKey");
                if (apiKey == null || apiKey.trim().isEmpty()) {
                    log.error("百度地图API密钥不能为空");
                    throw new IllegalArgumentException("Baidu Map API key is required");
                }
                baiduConfig.setAk(apiKey);

                // 设置默认值，确保配置完整
                baiduConfig.setDefaultCoordinateType("bd09ll"); // 百度地图默认坐标系
                baiduConfig.setCacheEnabled(true);
                baiduConfig.setCacheExpireSeconds(3600); // 1小时缓存过期
                baiduConfig.setLogEnabled(true);
                baiduConfig.setLogLevel("INFO");

                log.debug("创建百度地图配置: {}", baiduConfig);
                mapConfig = baiduConfig;
                break;
            case MOCK:
                MockConfig mockConfig = new MockConfig();
                mockConfig.setType(MapProviderType.MOCK);

                // 设置默认值，确保配置完整
                mockConfig.setDefaultCoordinateType("wgs84"); // 模拟地图默认使用WGS84坐标系
                mockConfig.setCacheEnabled(true);
                mockConfig.setCacheExpireSeconds(3600); // 1小时缓存过期
                mockConfig.setLogEnabled(true);
                mockConfig.setLogLevel("INFO");

                log.debug("创建模拟地图配置: {}", mockConfig);
                mapConfig = mockConfig;
                break;
            case AMAP:
                AmapConfig amapConfig = new AmapConfig();
                amapConfig.setType(MapProviderType.AMAP);

                String amapApiKey = (String) config.get("apiKey");
                if (amapApiKey == null || amapApiKey.trim().isEmpty()) {
                    log.error("高德地图API密钥不能为空");
                    throw new IllegalArgumentException("Amap API key is required");
                }
                amapConfig.setAk(amapApiKey);

                // 高德地图可能需要secretKey
                String secretKey = (String) config.get("secretKey");
                amapConfig.setSk(secretKey); // 可以为null

                // 设置默认值，确保配置完整
                amapConfig.setDefaultCoordinateType("gcj02"); // 高德地图默认坐标系
                amapConfig.setCacheEnabled(true);
                amapConfig.setCacheExpireSeconds(3600); // 1小时缓存过期
                amapConfig.setLogEnabled(true);
                amapConfig.setLogLevel("INFO");

                log.debug("创建高德地图配置: {}", amapConfig);
                mapConfig = amapConfig;
                break;
            default:
                log.error("不支持的地图服务商类型: {}", type);
                throw new IllegalArgumentException("Unsupported map provider type: " + type);
        }
        return mapConfig;
    }

    @Override
    public Map<String, Object> getCurrentConfig() throws MapException {
        try {
            // 如果当前配置为空，尝试从数据库加载
            if (currentConfig == null) {
                Config serviceConfig = configService.getConfig(SERVICE_TYPE, null);
                if (serviceConfig != null) {
                    Map<String, Object> configMap = AnyJsonUtils.parseMap(serviceConfig.getConfigJson());
                    currentConfig = createMapConfigFromMap(configMap);
                    currentMapService = MapServiceFactory.createMapService(currentConfig);
                    return configMap;
                }
                throw new MapException("Map configuration not found");
            }

            // 如果当前配置是默认的MOCK配置，返回null表示没有配置
            if (currentConfig.getType() != null && "MOCK".equals(currentConfig.getType().name())) {
                return null;
            }

           Config serviceConfig = configService.getConfig(SERVICE_TYPE, currentConfig.getType().name());
            if (serviceConfig == null) {
                throw new MapException("Map configuration not found");
            }
            return AnyJsonUtils.parseMap(serviceConfig.getConfigJson());
        } catch (Exception e) {
            log.error("获取地图配置失败: {}", e.getMessage(), e);
            throw new MapException("Failed to get map configuration", e);
        }
    }

    @Override
    public Map<String, Object> getConfigByProvider(String provider) throws MapException {
        try {
            log.info("根据提供商获取地图配置: {}", provider);
            Config serviceConfig = configService.getConfig(SERVICE_TYPE, provider);
            if (serviceConfig == null) {
                log.info("数据库中未找到{}类型的地图配置", provider);
                return null;
            }
            Map<String, Object> configMap = AnyJsonUtils.parseMap(serviceConfig.getConfigJson());
            log.info("成功获取{}类型的地图配置", provider);
            return configMap;
        } catch (Exception e) {
            log.error("根据提供商获取地图配置失败: {}", e.getMessage(), e);
            throw new MapException("Failed to get map configuration by provider: " + provider, e);
        }
    }
}
